﻿
using FastCtr;
using FastData;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Reflection;

namespace FastCtr
{
    //public static class lock_class
    //{
    //   // public static object lock_obj = new object();
    //}
    public enum FirstOrLast
    {
        First,
        Last,
    }


    public class SqlInformationBase
    {
        public static object lock_sql_base = new object();
        public string[] Key;
        public object[] KeyValue;
        public string[] Element;
        public  object[]  ElementValue;
        public string PrimaryKey = "Index";
        public object PrimaryKeyValue;
        public SqlInformationCollection<SqlInformationBase> ParentCollection;

        public virtual void FindAllProperty(out List<string> propertienames, out List<object> values)
        {
            Type type = GetType();
            propertienames = new List<string>();
            values = new List<object>();
            foreach (PropertyInfo p in type.GetProperties())
            {
                object v = p.GetValue(this);
                propertienames.Add(p.Name);
                values.Add(v);
            }
        }

        public virtual void SetSqlInformation()
        {
            List<string> listnames;
            List<object> values;
            this.FindAllProperty(out listnames, out values);
            if (PrimaryKey != null)
            {
                if (ParentCollection.newSQL.SqlClient.Update(ParentCollection.table, new string[] { PrimaryKey }, new object[] { PrimaryKeyValue }, listnames.ToArray(), values.ToArray()))
                {

                }
                else
                {
                    throw new Exception($"数据库更新信息异常PrimaryKey:{PrimaryKey},PrimaryKeyValue{PrimaryKeyValue}\r\n详细信息：\r\n变量名：{listnames.ToArray().ToString(",")}\r\n值：{values.ToArray().ToString(",")}");
                }
            }
            else
            {
                throw new Exception("不存在关键字或者元素字");
            }
        }

        public virtual void RemoveSqlInformation()
        {


            if (Key != null)
            {
                ParentCollection.RemoveKeyData(KeyValue);
            }
            else if (Element != null)
            {
                ParentCollection.RemoveElementData(ElementValue);
            }
            else
            {
                throw new Exception("不存在关键字或者元素字");
            }

        }
    }

    public class SqlInformationCollection<T>
    {
   
        public event Action<T> OnCreateNewSqlInformation;
        public NewSQL newSQL;
        public string table;
        public string[] Key;
        public string[] Element;
        public SqlInformationCollection(NewSQL _newSQL, string _tablename,params string[] _Key)
        {
            newSQL = _newSQL;
            table = _tablename;
            Key = _Key;
        }

        public T this[params string[] _KeyValue]
        {
            get
            {

                return GetKeySqlInformation(_KeyValue);

            }
        }

        public SqlInformationCollection<SqlInformationBase> ToSqlInformationCollectionBase()
        {
            SqlInformationCollection<SqlInformationBase> sqlInformationCollection = new SqlInformationCollection<SqlInformationBase>(newSQL, table, Key);
            return sqlInformationCollection;
        }


        public T CreateNewSqlInformation(params object[] _KeyValue)
        {

            dynamic cell = Activator.CreateInstance(typeof(T));
            cell.ParentCollection = this.ToSqlInformationCollectionBase();
            cell.Key = Key;
            cell.KeyValue = _KeyValue;
            if (Key.Length != _KeyValue.Length)
            {
                throw new Exception("关键字和关键值数量不一致，无法匹配");
            }
            for (int i = 0; i < Key.Length; i++)
            {
                cell.GetType().GetProperty(Key[i]).SetValue(cell, _KeyValue[i]);
            }
            List<string> listnames;
            List<object> values;
            cell.FindAllProperty(out listnames, out values);
            long id = 0;
            if (newSQL.SqlClient.Insert(table, listnames.ToArray(), values.ToArray(),ref id))
            {
                //DataSet ds = newSQL.SqlClient.GetData(table, cell.PrimaryKey, id.ToString());
                cell.PrimaryKeyValue = id;
                cell = GetElementSqlInformation(new string[] { cell.PrimaryKey }, new object[] { id })[0];
                OnCreateNewSqlInformation?.Invoke(cell);
            }
            else
            {
                throw new Exception($"数据库插入信息异常\r\n详细信息：\r\n变量名：{listnames.ToArray().ToString(",")}\r\n值：{values.ToArray().ToString(",")}");
            }
            return (T)cell;

        }

        public T GetKeySqlInformation(params Object[] _KeyValue)
        {
            dynamic cell = Activator.CreateInstance(typeof(T));
            cell.ParentCollection = this.ToSqlInformationCollectionBase();
            cell.Key = Key;
            cell.KeyValue = _KeyValue;
            DataSet dataSet = newSQL.SqlClient.GetData(table, Key, _KeyValue);
            if (Key.Length != _KeyValue.Length)
            {
                throw new Exception("关键字和关键值数量不一致，无法匹配");
            }
            if (dataSet.Tables[0].Rows.Count == 1)
            {
                cell.PrimaryKeyValue = dataSet.Tables[0].Rows[0].Field<object>((string)cell.PrimaryKey);
                foreach (PropertyInfo p in typeof(T).GetProperties())
                {
                    object v = dataSet.Tables[0].Rows[0].Field<object>(p.Name);
                    p.SetValue(cell, v);
                }
                return (T)cell;
            }
            else if (dataSet.Tables[0].Rows.Count > 1)
            {
                throw new Exception($"获取到关键字{_KeyValue.ToString(",")}的行数大于1");
            }
            else
            {
                throw new Exception($"查询到的数据库信息为空\r\n关键字：{Key.ToString(",")}，值{_KeyValue.ToString(",")}");
            }

        }

        public void SetElement(params string[] _Element)
        {
            Element = _Element;
        }

        public T[] GetElementSqlInformation(string[] _Element, params object[] _ElementValue)
        {
            
                Element = _Element;
                List<T> cells = new List<T>();
                DataSet dataSet = newSQL.SqlClient.GetData(table, Element, _ElementValue);
                if (dataSet.Tables[0].Rows.Count > 0)
                {
                    for (int k = 0; k < dataSet.Tables[0].Rows.Count; k++)
                    {
                        dynamic cell = Activator.CreateInstance(typeof(T));
                        cell.ParentCollection = this.ToSqlInformationCollectionBase();
                        cell.Element = Element;
                        cell.ElementValue = _ElementValue;
                        if (cell.Element.Length != cell.ElementValue.Length)
                        {
                            throw new Exception("查询字和查询值数量不一致，无法匹配");
                        }
                        cell.PrimaryKeyValue = dataSet.Tables[0].Rows[k].Field<object>((string)cell.PrimaryKey);
                        foreach (PropertyInfo p in typeof(T).GetProperties())
                        {
                            object v = dataSet.Tables[0].Rows[k].Field<object>(p.Name);
                            p.SetValue(cell, v);
                        }
                        cells.Add((T)cell);
                    }
                    return cells.ToArray();
                }
                else
                {
                    throw new Exception($"查询到的数据库元素数量为空\r\n查询元素：{Element.ToString(",")}值：{_ElementValue.ToString(",")}");
                }
            
        }


        public T GetElementOneSqlInformation(FirstOrLast firstOrLast,   string[] _Element, params object[] _ElementValue)
        {

            Element = _Element;
            List<T> cells = new List<T>();
            DataSet dataSet;
            if (firstOrLast == FirstOrLast.Last)
            {
                dataSet = newSQL.SqlClient.GetNewData(table, Element, _ElementValue);
            }
            else
            {
                dataSet = newSQL.SqlClient.GetFirstData(table, Element, _ElementValue);
            }

            if (dataSet.Tables[0].Rows.Count > 0)
            {

                dynamic cell = Activator.CreateInstance(typeof(T));
                cell.ParentCollection = this.ToSqlInformationCollectionBase();
                cell.Element = Element;
                cell.ElementValue = _ElementValue;
                if (cell.Element.Length != cell.ElementValue.Length)
                {
                    throw new Exception("查询字和查询值数量不一致，无法匹配");
                }
                cell.PrimaryKeyValue = dataSet.Tables[0].Rows[0].Field<object>((string)cell.PrimaryKey);
                foreach (PropertyInfo p in typeof(T).GetProperties())
                {
                    object v = dataSet.Tables[0].Rows[0].Field<object>(p.Name);
                    p.SetValue(cell, v);
                }
                return (T)cell;
            }
            else
            {
                throw new Exception($"查询到的数据库元素数量为空\r\n查询元素：{Element.ToString(",")}值：{_ElementValue.ToString(",")}");
            }

        }


        public T GetNextSqlInformation(SqlInformationBase sqlInformationBase, long MaxNextNum)
        {
            Element = sqlInformationBase.Element;
            //List<T> cells = new List<T>();
            DataSet dataSet;
            dynamic id = (long)sqlInformationBase.PrimaryKeyValue;

            while (true)
            {
                id++;
                dataSet = newSQL.SqlClient.GetData(table, sqlInformationBase.PrimaryKey, id.ToString());
                if (dataSet.Tables[0].Rows.Count > 0)
                {
                    dynamic cell = Activator.CreateInstance(typeof(T));
                    cell.ParentCollection = this.ToSqlInformationCollectionBase();
                    cell.PrimaryKeyValue = dataSet.Tables[0].Rows[0].Field<object>((string)cell.PrimaryKey);
                    foreach (PropertyInfo p in typeof(T).GetProperties())
                    {
                        object v = dataSet.Tables[0].Rows[0].Field<object>(p.Name);
                        p.SetValue(cell, v);
                    }
                    return (T)cell;
                }
                else
                {
                    if (id - (long)sqlInformationBase.PrimaryKeyValue > MaxNextNum)
                    {
                        return default(T);
                        //throw new Exception($"查询到的数据库元素数量为空\r\n查询上层信息为：{sqlInformationBase.PrimaryKey},值：{sqlInformationBase.PrimaryKeyValue },下层id间距{MaxNextNum}");

                    }
                }
            }
        }


        /// <summary>
        /// 多线程使用会有异常
        /// </summary>
        /// <param name="_ElementValue"></param>
        /// <returns></returns>
        public T[] GetElementSqlInformation(params object[] _ElementValue)
        {
            
                List<T> cells = new List<T>();
                DataSet dataSet = newSQL.SqlClient.GetData(table, Element, _ElementValue);
                if (dataSet.Tables[0].Rows.Count > 0)
                {
                    for (int k = 0; k < dataSet.Tables[0].Rows.Count; k++)
                    {
                        dynamic cell = Activator.CreateInstance(typeof(T));
                        cell.ParentCollection = this.ToSqlInformationCollectionBase();
                        cell.Element = Element;
                        cell.ElementValue = _ElementValue;
                        if (cell.Element.Length != cell.ElementValue.Length)
                        {
                            throw new Exception("查询字和查询值数量不一致，无法匹配");
                        }
                        cell.PrimaryKeyValue = dataSet.Tables[0].Rows[k].Field<object>((string)cell.PrimaryKey);
                        foreach (PropertyInfo p in typeof(T).GetProperties())
                        {
                            object v = dataSet.Tables[0].Rows[k].Field<object>(p.Name);
                            p.SetValue(cell, v);
                        }
                        cells.Add((T)cell);
                    }
                    return cells.ToArray();
                }
                else
                {
                    throw new Exception($"查询到的数据库元素数量为空\r\n查询元素：{Element.ToString(",")}值：{_ElementValue.ToString(",")}");
                }
            
        }

        public T GetLastSqlInformation()
        {
            dynamic cell = Activator.CreateInstance(typeof(T));
            cell.ParentCollection = this.ToSqlInformationCollectionBase();
            cell.Key = Key;
            Stopwatch sw = new Stopwatch();
            DataSet dataSet = newSQL.SqlClient.FindLastData(table);
            if (dataSet.Tables[0].Rows.Count == 1)
            {
                cell.PrimaryKeyValue = dataSet.Tables[0].Rows[0].Field<object>((string)cell.PrimaryKey);
                foreach (PropertyInfo p in typeof(T).GetProperties())
                {
                    object v = dataSet.Tables[0].Rows[0].Field<object>(p.Name);
                    p.SetValue(cell, v);
                }
                return (T)cell;
            }
            else if (dataSet.Tables[0].Rows.Count > 1)
            {
                throw new Exception($"获取到的行数大于1");
            }
            else
            {
                throw new Exception($"查询到的数据库最后一行信息为空\r\n关键字：{Key.ToString(",")}");
            }
        }

        public T GetFirstSqlInformation()
        {
           
                dynamic cell = Activator.CreateInstance(typeof(T));
                cell.ParentCollection = this.ToSqlInformationCollectionBase();
                cell.Key = Key;
                DataSet dataSet = newSQL.SqlClient.FindFirstData(table);
                if (dataSet.Tables[0].Rows.Count == 1)
                {
                    cell.PrimaryKeyValue = dataSet.Tables[0].Rows[0].Field<object>((string)cell.PrimaryKey);
                    foreach (PropertyInfo p in typeof(T).GetProperties())
                    {
                        object v = dataSet.Tables[0].Rows[0].Field<object>(p.Name);
                        p.SetValue(cell, v);
                    }
                    return (T)cell;
                }
                else if (dataSet.Tables[0].Rows.Count > 1)
                {
                    throw new Exception($"获取到的行数大于1");
                }
                else
                {
                    throw new Exception($"查询到的数据库第一行信息为空\r\n关键字：{Key.ToString(",")}");
                }
            
        }

        public T[] GetLastCountSqlInformation(int lastcount)
        {
           
                List<T> cells = new List<T>();
            
                DataSet dataSet = newSQL.SqlClient.FindLastLines(table, lastcount);
                if (dataSet.Tables[0].Rows.Count > 0)
                {
                    for (int k = 0; k < dataSet.Tables[0].Rows.Count; k++)
                    {
                        dynamic cell = Activator.CreateInstance(typeof(T));
                        cell.ParentCollection = this.ToSqlInformationCollectionBase();
                        cell.PrimaryKeyValue = dataSet.Tables[0].Rows[k].Field<object>((string)cell.PrimaryKey);
                        foreach (PropertyInfo p in typeof(T).GetProperties())
                        {
                            object v = dataSet.Tables[0].Rows[k].Field<object>(p.Name);
                            p.SetValue(cell, v);
                        }
                        cells.Add((T)cell);
                    }
                    return cells.ToArray();
                }
                else
                {
                    throw new Exception($"查询到的数据库数量为空\r\n查询表：{table} 最后几个数量：{lastcount}");
                }
            
        }


        public void RemoveKeyData(params object[] values)
        {


            int ret = newSQL.SqlClient.DeleteData(table, Key, values);
            if (ret == 0)
            {
                throw new Exception($"需要删除的关键字{Key.ToString(",")}={values.ToString(",")}行未找到");
            }


        }
        public void RemoveElementData(params object[] values)
        {

           
                int ret = newSQL.SqlClient.DeleteData(table, Element, values);
                if (ret == 0)
                {
                    throw new Exception($"需要删除的关键字{Element.ToString(",")}={values.ToString(",")}行未找到");
                }
            

        }

    }
}

